<!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<script>
(function() {
  'use strict';

  var Settings = Polymer.Settings;
  var TreeApi = Polymer.TreeApi;
  var DomApi = Polymer.DomApi;

  // *************** Configure DomApi for Shadow DOM!! ***************
  if (!Settings.useShadow) {
    return;
  }

  Polymer.Base.mixin(DomApi.prototype, {

    querySelectorAll: function(selector) {
      return TreeApi.arrayCopy(this.node.querySelectorAll(selector));
    },

    getOwnerRoot: function() {
      var n = this.node;
      while (n) {
        if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE && n.host) {
          return n;
        }
        n = n.parentNode;
      }
    },

    importNode: function(externalNode, deep) {
      var doc = this.node instanceof Document ? this.node :
        this.node.ownerDocument;
      return doc.importNode(externalNode, deep);
    },

    getDestinationInsertionPoints: function() {
      var n$ = this.node.getDestinationInsertionPoints &&
        this.node.getDestinationInsertionPoints();
      return n$ ? TreeApi.arrayCopy(n$) : [];
    },

    getDistributedNodes: function() {
      var n$ = this.node.getDistributedNodes &&
        this.node.getDistributedNodes();
      return n$ ? TreeApi.arrayCopy(n$) : [];
    }

  });

  Object.defineProperties(DomApi.prototype, {

    activeElement: {
      get: function() {
        var node = DomApi.wrap(this.node);
        var activeElement = node.activeElement;
        // Prevents `activeElement` from returning elements outside of the
        // ShadowRoot, even if they would become descendants of the ShadowRoot
        // in the composed tree. See w3c/webcomponents#358.
        return node.contains(activeElement) ? activeElement : null;
      },
      configurable: true
    },

    childNodes: {
      get: function() {
        return TreeApi.arrayCopyChildNodes(this.node);
      },
      configurable: true
    },

    children: {
      get: function() {
        return TreeApi.arrayCopyChildren(this.node);
      },
      configurable: true
    },

    // textContent / innerHTML
    textContent: {
      get: function() {
        return this.node.textContent;
      },
      set: function(value) {
        return this.node.textContent = value;
      },
      configurable: true
    },

    innerHTML: {
      get: function() {
        return this.node.innerHTML;
      },
      set: function(value) {
        return this.node.innerHTML = value;
      },
      configurable: true
    }

  });

  var forwardMethods = function(m$) {
    for (var i=0; i < m$.length; i++) {
      forwardMethod(m$[i]);
    }
  };

  var forwardMethod = function(method) {
    DomApi.prototype[method] = function() {
      return this.node[method].apply(this.node, arguments);
    }
  };

  forwardMethods(['cloneNode', 'appendChild', 'insertBefore',
    'removeChild', 'replaceChild', 'setAttribute', 'removeAttribute',
    'querySelector']);

  var forwardProperties = function(f$) {
    for (var i=0; i < f$.length; i++) {
      forwardProperty(f$[i]);
    }
  };

  var forwardProperty = function(name) {
    Object.defineProperty(DomApi.prototype, name, {
      get: function() {
        return this.node[name];
      },
      configurable: true
    });
  };

  forwardProperties(['parentNode', 'firstChild', 'lastChild',
    'nextSibling', 'previousSibling', 'firstElementChild',
    'lastElementChild', 'nextElementSibling', 'previousElementSibling']);

})();
</script>
